using GameGraphics.HomeWorld;
using GameUnityFramework.Resource;
using System;
using GameBaseFramework.Base;
using GameBaseFramework.Extension;
using Unity.VisualScripting;
using UnityEditor.SearchService;
using UnityEngine;
using UnityEngine.EventSystems;
using Vector3 = UnityEngine.Vector3;

namespace GameGraphics
{
    public enum CameraMoveMode
    {
        /// <summary>
        /// 平移
        /// </summary>
        Translate,

        /// <summary>
        /// 旋转
        /// </summary>
        Rotate
    }

    public class PointerData
    {

        /// <summary>
        /// 是否按下
        /// </summary>
        public bool IsPointerDown = false;

        /// <summary>
        /// 按下时鼠标对应的位置
        /// </summary>
        public Vector2 PointerDownMousePosition;

        /// <summary>
        /// 原始EventSystem消息
        /// </summary>
        public PointerEventData PointerEventData;

        /// <summary>
        /// 上一次按下时间
        /// </summary>
        public DateTime lastClickTime;
    }


    public class UIViewBottomMax : UIViewBottomMaxBase, IPointerDownHandler, IPointerClickHandler, IPointerUpHandler, IDragHandler
    {
        /// <summary>
        /// 主摄像机
        /// </summary>
        public static Camera MainCamera;

        /// <summary>
        /// Select框
        /// </summary>
        public RectTransform _RectSelect;

        /// <summary>
        /// 左键鼠标事件
        /// </summary>
        private readonly PointerData _leftMousePointerData = new();

        /// <summary>
        /// 右键鼠标事件
        /// </summary>
        private readonly PointerData _rightMousePointerData = new();

        /// <summary>
        /// 中键鼠标事件
        /// </summary>
        private readonly PointerData _middleMousePointerData = new();

        /// <summary>
        /// 鼠标中键开始拖拽时的位置
        /// </summary>
        private Vector3 _dragStartPosition;

        /// <summary>
        /// 镜头移动模式
        /// </summary>
        private CameraMoveMode _moveMode = CameraMoveMode.Translate;


        protected override void OnEnter(object data = null)
        {
            base.OnEnter(data);
            if (MainCamera == null) MainCamera = Camera.main;
            if (_RectSelect == null) _RectSelect = _gameobjectSelect.GetComponent<RectTransform>();
        }

        public void OnPointerDown(PointerEventData eventData)
        {
            DebugTool.Log(eventData.button.ToString());
            switch (eventData.button)
            {
                case PointerEventData.InputButton.Left:
                    SetPointerDownEvent(_leftMousePointerData, eventData);

                    break;
                case PointerEventData.InputButton.Right:
                    SetPointerDownEvent(_rightMousePointerData, eventData);
                    break;
                case PointerEventData.InputButton.Middle:
                    SetPointerDownEvent(_middleMousePointerData, eventData);
                    GetDragStartPosition();
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }
        }

        private void SetPointerDownEvent(PointerData pointerData, PointerEventData eventData, bool IsPointerDown = true)
        {
            pointerData.IsPointerDown = IsPointerDown;
            pointerData.PointerDownMousePosition = eventData.position;
            pointerData.PointerEventData = eventData;
            pointerData.lastClickTime = DateTime.Now;
        }

        public void OnPointerClick(PointerEventData eventData)
        {
            DebugTool.Log();
        }

        public void OnPointerUp(PointerEventData eventData)
        {
            DebugTool.Log(eventData.button.ToString());
            switch (eventData.button)
            {
                case PointerEventData.InputButton.Left:
                    _leftMousePointerData.IsPointerDown = false;
                    _gameobjectSelect.SetActive(false);
                    RTS_SelectTarget();
                    break;
                case PointerEventData.InputButton.Right:
                    _rightMousePointerData.IsPointerDown = false;
                    break;
                case PointerEventData.InputButton.Middle:
                    _middleMousePointerData.IsPointerDown = false;
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }
        }

        public void OnDrag(PointerEventData eventData)
        {
            switch (eventData.button)
            {
                case PointerEventData.InputButton.Left:
                    HandleLeftDrag(eventData);
                    break;
                case PointerEventData.InputButton.Right:
                    HandleRightDrag(eventData);
                    break;
                case PointerEventData.InputButton.Middle:
                    HandleMiddleDrag(eventData);
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }
        }

        /// <summary>
        /// 选择框中的所有单位
        /// </summary>
        private void RTS_SelectTarget()
        {
            Vector2 pointA = _gameobjectSelect.transform.position;
            Vector2 pointB = pointA + _gameobjectSelect.transform.localScale * _RectSelect.sizeDelta * new Vector2(1, -1);

            var hitA = Raycast(pointA, "VirtualGround");
            var hitB = Raycast(pointB, "VirtualGround");

            if (hitA == null || hitB == null)
            {
                //什么都没有选中
                return;
            }

            hitA.Value.point.LogJson();
            hitB.Value.point.LogJson();
            //var obj1 = GameObject.CreatePrimitive(PrimitiveType.Sphere);
            //obj1.transform.position = hitA.Value.point;
            //var obj2 = GameObject.CreatePrimitive(PrimitiveType.Sphere);
            //obj2.transform.position = hitB.Value.point;
            //计算Box
            var Center = (hitA.Value.point + hitB.Value.point) / 2;
            var delta = (hitA.Value.point - hitB.Value.point);
            var halfExtents = new Vector3(Mathf.Abs(delta.x) / 2, 20f, Mathf.Abs(delta.z) / 2);

            var hits = Physics.BoxCastAll(Center, halfExtents, Vector3.up, Quaternion.identity, 50f);
            Center.LogJson();
            halfExtents.LogJson();
            if (hits != null)
            {
                foreach (var i in hits)
                {
                    DebugTool.Log(i.collider.gameObject.name);
                }
            }
        }

        /// <summary>
        /// 获取拖动开始的位置
        /// </summary>
        private void GetDragStartPosition()
        {
            var hit = Raycast(_middleMousePointerData.PointerEventData.position, "VirtualGround");
            if (hit.HasValue)
            {
                _dragStartPosition = hit.Value.point;
            }
            hit = Raycast(new Vector2(Screen.width * 0.5f, Screen.height * 0.5f), "VirtualGround");
            if (hit.HasValue)
            {
                DragStartMiddlePosition = hit.Value.point;
                DragStartCameraVector = (MainCamera.transform.position - DragStartMiddlePosition).FromCarteToSphere();
            }
            _moveMode = Input.GetKey(KeyCode.Space) ? CameraMoveMode.Rotate : CameraMoveMode.Translate;
        }

        /// <summary>
        /// 拖动开始时摄像机的位置，球坐标系
        /// </summary>
        public Vector3 DragStartCameraVector { get; set; }

        /// <summary>
        /// 拖动开始时相机的位置
        /// </summary>
        public Vector3 DragStartMiddlePosition { get; set; }

        /// <summary>
        /// 拖动框
        /// </summary>
        /// <param name="eventData"></param>
        private void HandleLeftDrag(PointerEventData eventData)
        {
            _gameobjectSelect.SetActive(true);

            _gameobjectSelect.transform.position = _leftMousePointerData.PointerDownMousePosition;
            var size= (eventData.position - _leftMousePointerData.PointerDownMousePosition) * new Vector2(1f, -1f);
            var scale = Vector3.one;
            if (size.x < 0)
            {
                size.x = -size.x;
                scale.x = -1;
            }
            else
            {
                scale.x = 1;
            }
            if (size.y < 0)
            {

                size.y = -size.y;
                scale.y = -1;
            }
            else
            {
                scale.y = 1;
            }

            _RectSelect.sizeDelta = size;
            _gameobjectSelect.transform.localScale = scale;
        }

        /// <summary>
        /// 无需操作
        /// </summary>
        /// <param name="eventData"></param>
        private void HandleRightDrag(PointerEventData eventData)
        {
            var hit = Raycast(_rightMousePointerData.PointerEventData.position, "VirtualGround");
            if (hit.HasValue)
            {
                var v1 = hit.Value.point - _dragStartPosition;
            }
        }

        /// <summary>
        /// 拖动屏幕
        /// </summary>
        /// <param name="eventData"></param>
        private void HandleMiddleDrag(PointerEventData eventData)
        {
            if (Input.GetKey(KeyCode.Space))
            {
                //旋转模式
                RotateCamera();
            }
            else
            {
                //平移模式
                TranslateCamera();
            }

        }

        /// <summary>
        /// 旋转相机
        /// </summary>
        private void RotateCamera()
        {
            var hit = Raycast(_middleMousePointerData.PointerEventData.position, "VirtualGround");
            if (hit.HasValue)
            {
                var v1 = (hit.Value.point - DragStartMiddlePosition);
                var v2 = (_dragStartPosition - DragStartMiddlePosition);
                float angle = Vector3.SignedAngle(v1, v2,  Vector3.up);
                MainCamera.transform.position = (MainCamera.transform.position - DragStartMiddlePosition).RotateY(angle) + DragStartMiddlePosition;
                MainCamera.transform.LookAt(DragStartMiddlePosition);
            }
        }

        /// <summary>
        /// 平移相机
        /// </summary>
        private void TranslateCamera()
        {
            var hit = Raycast(_middleMousePointerData.PointerEventData.position, "VirtualGround");
            if (hit.HasValue)
            {
                var v1 = hit.Value.point - _dragStartPosition;
                MainCamera.transform.position -= v1;
            }
        }

        /// <summary>
        /// 从屏幕空间发射一条射线，来检测目标Layer的物体
        /// </summary>
        /// <param name="Position"></param>
        /// <param name="LayerName"></param>
        public static RaycastHit? Raycast(Vector2 position, string raycastLayer)
        {
            var ray = MainCamera.ScreenPointToRay(position);
            var layer = 1 << LayerMask.NameToLayer(raycastLayer);
            if (Physics.Raycast(ray, out var hit, Mathf.Infinity, layer))
            {
                return hit;
            }
            return null;
        }

    }
}
